home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume24 / mkid2 / part04 < prev    next >
Encoding:
Internet Message Format  |  1991-10-09  |  38.4 KB

  1. Subject:  v24i092:  Program identifier database tools, Part04/07
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: b8a0c027 3f0a9f92 de21f474 5deb2873
  5.  
  6. Submitted-by: Tom Horsley <tom@hcx2.ssd.csd.harris.com>
  7. Posting-number: Volume 24, Issue 92
  8. Archive-name: mkid2/part04
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 4 (of 7)."
  17. # Contents:  TUTORIAL iid.y scan-c.c
  18. # Wrapped by tom@hcx2 on Tue Feb 26 10:03:04 1991
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'TUTORIAL' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'TUTORIAL'\"
  22. else
  23. echo shar: Extracting \"'TUTORIAL'\" \(16037 characters\)
  24. sed "s/^X//" >'TUTORIAL' <<'END_OF_FILE'
  25. X
  26. XThis is a program identifier database package.  These tools provide a
  27. Xlogical extension to ctags. (which is limited in that it only stores the
  28. Xlocation of function and type *definitions*a)  The ID facility
  29. Xstores the locations for all uses of identifiers, pre-processor
  30. Xnames, and numbers. (in decimal, octal or hex)
  31. X
  32. XWhen fixing or enhancing a large program (particularly one that is
  33. Xunfamiliar) it is often necessary to audit the use of global
  34. Xdata-structures in order to verify that the proposed modification will
  35. Xnot trigger any hidden `gotchas'.  Often this entails grepping through
  36. Xmany thousands of lines of source code spread over dozens and sometimes
  37. Xhundreds of source files in multiple sub-directories.  This process
  38. Xplaces a significant load on computing resources, and takes a long
  39. Xtime.  There is even the danger that a programmer will avoid doing a
  40. Xcomplete audit due to the perceived cost--he or she will rely on memory
  41. Xand hope that there are no booby traps.
  42. X
  43. XThe id-database is most useful for maintaining large programs that
  44. Xconsist of many source files.  The database is simply a two dimensional
  45. Xboolean array indexed by identifier-name and source-file-name.  For a
  46. Xgiven identifier and source-file, if the identifier occurs in the file,
  47. Xthe boolean value is TRUE.  The database may be queried either by
  48. Xidentifier-name or file-name.
  49. X
  50. XThe following types of queries supported:
  51. X
  52. X* name lookup
  53. X    list all the files where an identifier occurs.  The name
  54. X    may be a regular expression.
  55. X
  56. X* name apropos
  57. X    list all the files for all identifiers that have the sub-string
  58. X    name in them.  Matches are done in a case-insensitive mammer.
  59. X
  60. X* name `grep'
  61. X    search for an identifier in all the files where it occurs.
  62. X    This is an optimized `grep' over all the sources--we only
  63. X    search on files that contain the identifier.
  64. X
  65. X* name edit
  66. X    invoke an editor on the files where an identifier occurs,
  67. X    and use the identifier as an initial search string.
  68. X
  69. X* file lookup
  70. X    list all identifiers that occur in a file, or list
  71. X    the identifiers that are common between two files.
  72. X
  73. X* non-unique names
  74. X    list the names of all indentifiers whose names are non-unique
  75. X    within some number of characters.  This is useful when porting
  76. X    a program from a `flexnames' system to one more limited names.
  77. X
  78. X* solo
  79. X    list all identifiers that occur exactly once in a software
  80. X    system.  This may be useful for locating identifiers that are
  81. X    declared but never used, or library functions that are used
  82. X    but never declared.
  83. X    
  84. X
  85. XThe first four queries are handled by one program.  The type of query
  86. Xis determined by the name the program was invoked with.  The four links
  87. Xare lid(1) for `lookup id', aid(1) for `apropos id', gid(1) for `grep
  88. Xid' and eid(1) for `edit id'.  One or more identifiers may be passed on
  89. Xthe command line.  The identifiers may be literal strings or regular
  90. Xexpressions.  Here are some examples:
  91. X
  92. X$ lid FILE
  93. XFILE           extern.h {fid,gets0,getsFF,idx,init,lid,mkid,opensrc,scan-asm,scan-c}.c
  94. X
  95. X$ lid FILE$
  96. XAF_FILE        mkid.c
  97. XAF_IDFILE      mkid.c
  98. XFILE           extern.h {fid,gets0,getsFF,idx,init,lid,mkid,opensrc,scan-asm,scan-c}.c
  99. XIDFILE         id.h {fid,lid,mkid}.c
  100. XIdFILE         {fid,lid}.c
  101. XargFILE        mkid.c
  102. XgidFILE        lid.c
  103. XidFILE         {init,mkid}.c
  104. XinFILE         {gets0,getsFF,scan-asm,scan-c}.c
  105. XopenSrcFILE    extern.h {idx,mkid,opensrc}.c
  106. XsrcFILE        {idx,mkid,opensrc}.c
  107. X
  108. X$ lid ^get
  109. Xget            opensrc.c
  110. XgetAdaId       getscan.c
  111. XgetAsmId       extern.h {getscan,scan-asm}.c
  112. XgetCId         extern.h {getscan,scan-c}.c
  113. XgetDirToName   extern.h {fid,lid,paths}.c
  114. XgetId          {idx,mkid}.c
  115. XgetLanguage    extern.h {getscan,idx,mkid}.c
  116. XgetLispId      getscan.c
  117. XgetPascalId    getscan.c
  118. XgetRoffId      getscan.c
  119. XgetSCCS        extern.h opensrc.c
  120. XgetScanner     extern.h {getscan,idx,mkid}.c
  121. XgetTeXId       getscan.c
  122. XgetTextId      getscan.c
  123. Xgetc           {gets0,getsFF,lid,scan-asm,scan-c}.c
  124. Xgetchar        lid.c
  125. Xgetenv         extern.h lid.c
  126. Xgets           lid.c
  127. XgetsFF         extern.h {bitsvec,fid,getsFF,lid,mkid}.c
  128. X
  129. XAs you can see, when a regular expression is used, it is possible to
  130. Xget more than one line of output.  If you wish multiple lines to be
  131. Xmerged into one, supply the `-m' option:
  132. X
  133. X$ lid -m ^get
  134. X^get           extern.h {bitsvec,fid,gets0,getsFF,getscan,idx,lid,mkid,opensrc,paths,scan-asm,scan-c}.c
  135. X
  136. XThe query program searches for numbers numerically rather than
  137. Xtextually.  Therefore you may search for multiple representations of a
  138. Xnumber.  It is best to illustrate this with examples:
  139. X
  140. X$ lid -a 0x10
  141. X020            numtst.c
  142. X0x00010        numtst.c
  143. X0x0010         scan-c.c
  144. X0x10           {id,radix}.h {scan-asm,stoi}.c
  145. X16             numtst.c
  146. X
  147. XThe `-a' argument tells lid(1) to look for 0x10 in all radixes.  (For
  148. Xnumbers 0 through 7, lid(1) looks for all radixes by default.  For numbers
  149. Xgreater than 7, lid(1) only looks for the radix that the argument is
  150. Xsupplied in.) It is also possible to restrict the search to selected
  151. Xradixes by supplying an argument consisting of one or more of the
  152. Xkey-letters `o', `d', and `x' for octal decimal and hexadecimal
  153. Xrespectively:
  154. X
  155. X$ lid -o 0x10
  156. X020            numtst.c
  157. X
  158. X$ lid -x 16
  159. X0x00010        numtst.c
  160. X0x0010         scan-c.c
  161. X0x10           {id,radix}.h  {scan-asm,stoi}.c
  162. X
  163. X$ lid -d 020
  164. X16             numtst.c
  165. X
  166. X
  167. XThe grep interface behaves somewhat like the following command:
  168. X
  169. X$ grep -w -n `lid TRUE`
  170. X
  171. XHeres some sample output for the equivalent gid command:
  172. X
  173. X$ gid TRUE
  174. Xbool.h:5: #define    TRUE    (0==0)
  175. Xlid.c:102:         case 'm': forceMerge = TRUE; break;
  176. Xlid.c:170:             Merging = TRUE;
  177. Xlid.c:204:             crunching = TRUE;
  178. Xlid.c:553:             hitDigits = TRUE;
  179. Xlid.c:787:             return TRUE;
  180. Xmkid.c:117:             Verbose = TRUE;
  181. Xmkid.c:191:                     keepLang = TRUE;
  182. Xscan-asm.c:79: static bool eatUnder = TRUE;
  183. Xscan-asm.c:80: static bool preProcess = TRUE;
  184. Xscan-asm.c:96:     static bool    newLine = TRUE;
  185. Xscan-asm.c:130:         newLine = TRUE;
  186. Xscan-asm.c:141:         newLine = TRUE;
  187. Xscan-asm.c:145:         newLine = TRUE;
  188. Xscan-asm.c:150:         newLine = TRUE;
  189. Xscan-asm.c:165:                 newLine = TRUE;
  190. Xscan-c.c:88: static bool eatUnder = TRUE;
  191. Xscan-c.c:101:     static bool    newLine = TRUE;
  192. Xscan-c.c:138:         newLine = TRUE;
  193. Xscan-c.c:199:                 newLine = TRUE;
  194. Xscan-c.c:205:         newLine = TRUE;
  195. Xscan-c.c:210:             newLine = TRUE;
  196. Xwmatch.c:37:             return TRUE;
  197. X
  198. XNotice that each line is reported in the same format as a
  199. XC-preprocessor error message.  This feature allows gid(1) lines to be
  200. Xdigested by any program that parses error messages, such as error(1)
  201. Xand gnu-emacs.
  202. X
  203. XIf you want to edit all files that have an identifier, you may
  204. Xconveniently do so with eid(1):
  205. X
  206. X$ eid TRUE
  207. XTRUE           bool.h {lid,mkid,scan-asm,scan-c,wmatch}.c
  208. XEdit? [y1-9^S/nq] 
  209. X
  210. XBefore the editor is invoked, you are given the lid(1) output to review
  211. Xand comfirm.  If you want to edit all files listed, respond with a
  212. Xnewline or with `y'.  If you want to skip some number of files into the
  213. Xargument list, respond with a single digit `1' through `9' to skip that
  214. Xmany files, or do a string-search to the first file you want with
  215. X`^S<string>' or `/<string>'.  If you don't want to edit anything, type
  216. X`n' to go on to the next argument you gave to eid(1) or type `q' to
  217. Xquit altogether.
  218. X
  219. XThe behavior of the editing interface is controlled by three
  220. Xenvironment variables called EIDARG, EIDLDEL, and EIDRDEL.  The best
  221. Xway to illustrate their use by an example.  Here is how to define them
  222. Xfor vi(1) (using /bin/sh syntax)
  223. X
  224. XEIDARG='+/%s/'    # printf(3) string for initial search-string argument
  225. XEIDLDEL='\<'    # left word-delimiter
  226. XEIDRDEL='\>'    # right word-delimiter
  227. X
  228. X`EID[LR]DEL' are positioned around the identifier as left and right
  229. Xword-delimiters if your editor supports that notion.  Then the whole
  230. Xname-string is sprintf(3)'ed into `EIDARG' to construct the initial
  231. Xsearch-string argument to the editor.  If your editor can't digest such
  232. Xan argument, simply leave these variables undefined in the
  233. Xenvironment.
  234. X
  235. XSome emacs users are appalled at the notion of starting up a fresh editor
  236. Xsimply to follow an identifier.  For those who are fortunate enough to have
  237. Xa programmable emacs such as gnu-emacs, it is fairly simple to devise
  238. Xa command that invokes gid(1) and digests its output as though it were
  239. X/lib/cpp error strings to be examined.  (Sorry, no such code is provided
  240. Xat this posting...)
  241. X
  242. XAnother type of query is to find all identifiers that are non-unique
  243. Xwithin some number of characters.  This is useful for finding potential
  244. Xportability problems when moving to a system whose compiler or linker
  245. Xlimits the number of significant characters in a name.  The `-u<n>'
  246. Xargument does the trick.  Here's a list of identifiers that may yield
  247. Xmultiply-defined errors in a symbol table that only knows about the
  248. Xfirst 7 characters:
  249. X
  250. X$ lid -u7
  251. XSCAN_TEX       getscan.c
  252. XSCAN_TEXT      getscan.c
  253. Xidh_argc       id.h {init,mkid}.c
  254. Xidh_argo       id.h {init,mkid}.c
  255. Xidh_namc       id.h {fid,mkid}.c
  256. Xidh_namo       id.h {fid,init,lid,mkid}.c
  257. XoldHashSize    mkid.c
  258. XoldHashTable   mkid.c
  259. X
  260. XBetter yet, if you want to edit these, try
  261. X
  262. X$ eid -u7
  263. X^SCAN_TE       getscan.c
  264. XEdit? [y1-9^S/nq] n
  265. X^idh_arg       getscan.c id.h {init,mkid}.c
  266. XEdit? [y1-9^S/nq] n
  267. X^idh_nam       {fid,getscan}.c id.h {init,lid,mkid}.c
  268. XEdit? [y1-9^S/nq] n
  269. X^oldHash       {fid,getscan}.c id.h {init,lid,mkid}.c
  270. XEdit? [y1-9^S/nq] n
  271. X
  272. X
  273. XAn additional feature of lid(1) is that pathnames are automatically
  274. Xadjusted for the current working directory.  Large programs such as the
  275. XUNIX kernel are often partitioned into subsystems whose sources live in
  276. Xdifferent directories.  What follows are several examples of the same
  277. Xsearch conducted from different points in the UNIX kernel source
  278. Xhierarchy:
  279. X
  280. X$ cd /src/uts/m68k
  281. X$ lid bdevsw
  282. Xbdevsw         sys/conf.h  cf/conf.c  io/bio.c  os/{fio,main,prf,sys3}.c
  283. X
  284. X$ cd io
  285. X$ lid bdevsw
  286. Xbdevsw         ../sys/conf.h  ../cf/conf.c  bio.c  ../os/{fio,main,prf,sys3}.c
  287. X
  288. X$ cd ../os
  289. Xbdevsw         ../sys/conf.h  ../cf/conf.c  ../io/bio.c  {fio,main,prf,sys3}.c
  290. X
  291. XThe database is built with mkid(1).  The user supplies pathnames
  292. Xeither on the command line or on stdin.  Here's the output of the
  293. X`verbose' option to mkid(1):
  294. X
  295. X$ mkid -v *.h *.c
  296. Xc: bitops.h
  297. Xc: bool.h
  298. Xc: extern.h
  299. Xc: id.h
  300. Xc: patchlevel.h
  301. Xc: radix.h
  302. Xc: string.h
  303. Xc: basename.c
  304. Xc: bitcount.c
  305. Xc: bitops.c
  306. Xc: bitsvec.c
  307. Xc: bsearch.c
  308. Xc: bzero.c
  309. Xc: document.c
  310. Xc: fid.c
  311. Xc: gets0.c
  312. Xc: getsFF.c
  313. Xc: getscan.c
  314. Xc: hash.c
  315. Xc: idx.c
  316. Xc: init.c
  317. Xc: lid.c
  318. Xc: mkid.c
  319. Xc: numtst.c
  320. Xc: opensrc.c
  321. Xc: paths.c
  322. Xc: scan-asm.c
  323. Xc: scan-c.c
  324. Xc: stoi.c
  325. Xc: tty.c
  326. Xc: uerror.c
  327. Xc: wmatch.c
  328. XCompressing Hash Table...
  329. XSorting Hash Table...
  330. XWriting `ID'...
  331. XNames: 593, Numbers: 64, Strings: 43, Solo: 119, Total: 697
  332. XOccurrances: 11.67, Load: 0.17, Probes: 1.07
  333. X
  334. XMkid(1) echoes the name of each file as it is scanned, prefixed by the
  335. Xname of the language it thinks the file is written in.  Mkid(1) reports
  336. Xhow many unique names and numbers were found, how many names occurred
  337. Xonly once, and the total for names and numbers.  It also reports the
  338. Xaverage number of occurrances for all names and numbers.  Next, there
  339. Xare some hash-table statistics on the load-factor and the average
  340. Xnumber of open-addressed probes.
  341. X
  342. XMkid(1) can take arguments from the command line, from stdin, or from
  343. Xa file.  A file full of filenames may also contain mkid options of the form
  344. X-<option>.  Filenames and options appear in the file one-per-line.  Typical
  345. Xusage for this feature is as follows:
  346. X
  347. X$ find . -name '*.[chys]' -print >IDFILES
  348. X$ mkid -aIDFILES
  349. X
  350. X-- or --
  351. X
  352. X$ find . -name '*.[chys]' -print |mkid -
  353. X
  354. XMkid(1) stashes the filenames and relevant arguments in the database
  355. Xitself.  It uses these to support the ``incremental-update' option.
  356. XIf invoked with `-u', mkid(1) checks the modification times of all
  357. Xconstituent files, and only re-scans those that are newer than the
  358. Xdatabase itself.  It is invoked like so:
  359. X
  360. X$ mkid -u
  361. X
  362. XIn summation, mkid(1) can get arguments from one of four places:
  363. X1) the command line, 2) a file, 3) stdin, 4) the database itself.
  364. X
  365. XMkid(1) accepts a number of scanner-specific arguments.  Generally,
  366. Xthese are introduced with `-S<lang>' where <lang> is the name of
  367. Xa language, such as `c' or `asm'.  You can get a scanner-specific
  368. Xusage-report with `-S<lang>?'  (Of course, the `?' must be escaped
  369. Xto get it past the shell)
  370. X
  371. XHere's scanner-usage for the assembly language scanner:
  372. X
  373. X$ mkid -Sasm\?
  374. XThe Assembler scanner arguments take the form -Sasm<arg>, where
  375. X<arg> is one of the following: (<cc> denotes one or more characters)
  376. X  -c<cc> . . . . <cc> introduce(s) a comment until end-of-line.
  377. X  (+|-)u . . . . (Do|Don't) strip a leading `_' from ids.
  378. X  (+|-)a<cc> . . Allow <cc> in ids, and (keep|ignore) those ids.
  379. X  (+|-)p . . . . (Do|Don't) handle C-preprocessor directives.
  380. X  (+|-)C . . . . (Do|Don't) handle C-style comments. (/* */)
  381. X
  382. X`-Sasm-c<cc>' tells the scanner what characters are used to introduce comments
  383. Xthat extend to end-of-line.
  384. X
  385. XUse `-Sasm+u' if your C compiler prepends leading underscores to external
  386. Xnames.  This way, mkid(1) will strip leading underscores, and the name
  387. X`foo' in a C source will be correctly associated with the name `_foo'
  388. Xin an assembler source.  If your compiler doesn't prepend leading
  389. Xunderscores, use `-Sasm-u'.
  390. X
  391. XMany assemblers allow special characters to be mixed with
  392. Xalpha-numerics in label, constant and register names.  Common choices
  393. Xare `.', `%', and `$'.  Thus, a label such as `L%123' should be scanned
  394. Xas one token, not broken up into the name `L' and the number 123.
  395. X`-Sasm-a%.' tells the scanner to allow `%' and `.' in tokens, but to throw
  396. Xaway tokens containing `%' or `.' `-Sasm+a%.' tells the scanner to keep such
  397. Xtokens and put them into the database.
  398. X
  399. X
  400. X`-Sasm+p' tells the scanner to handle `#include' and `#define' lines as
  401. Xin C source, and `-Sasm+C' tells it to ignore C-style comments.
  402. X
  403. XHere's the scanner-usage for C:
  404. X
  405. X$ mkid -Sc\?
  406. XThe C scanner arguments take the form -Sc<arg>, where <arg>
  407. Xis one of the following: (<cc> denotes one or more characters)
  408. X  (+|-)u . . . . (Do|Don't) strip a leading `_' from ids in strings.
  409. X  -s<cc> . . . . Allow <cc> in string ids.
  410. X
  411. XThe `+u' argument is akin to the argument for the assembly-language
  412. Xscanner.  Mkid(1) keeps the contents of quoted-strings if the string
  413. Xcontains a single valid C name and nothing else.  E.g.  mkid(1) would
  414. Xkeep the contents of "_proc".  Such strings are interesting because
  415. Xthey may contain symbol names that a program uses for nlist lookups.
  416. XSo, if your compiler prepends underscores to external symbols, use
  417. X`-Sc+u' so that mkid(1) will strip them back off.
  418. X
  419. XMkid(1) normally throws away the contents of quoted strings that have
  420. Xanything other than a single name in them.  You can tell mkid(1) to
  421. Xaccept additional characters in strings with `-Sc-s<cc>' where <cc> is
  422. Xone or more special characters.  E.g. `-Sc-s/.-:,' will include most of
  423. Xthe strings containing pathnames that you are likely to encounter.
  424. X
  425. XAnother class of scanner argument allows you to associate a suffix
  426. Xwith a language.  E.g. `-S.y=c' tells mkid(1) to use the C language
  427. Xscanner on all files ending with .y.  You can ask mkid(1) for the
  428. Xavailable scanners and associated suffixes like so:
  429. X
  430. X$ mkid -S\?=\?
  431. X.c=c, .h=c, .y=c, .s=asm, .p=pascal, .pas=pascal
  432. X
  433. XPlease note, mkid(1) is lying to you about its Pascal prowess!
  434. XAt the time of this posting, there are scanners for C and assembly
  435. Xlanguage sources.  There are also stubs for Pascal, Ada and LISP.  The
  436. Xscanners are very fast.  The assembly language scanner knows how
  437. Xto throw away C-style comments as well as the traditional `comment-
  438. Xcharacter-until-end-of-line' style.  In order to test new scanners,
  439. Xthere is a scanner driver called idx(1).  Idx(1) simply calls the
  440. Xscanner to get identifiers one-at-a-time prints them on stdout one-per-line.
  441. X
  442. XFor more information, read the manual pages!
  443. X
  444. XHappy Hacking,
  445. X--
  446. X-- Greg McGary
  447. X-- P.O. Box 286
  448. X-- Lincoln, MA  01773
  449. X--
  450. X-- 9/15/87
  451. X--
  452. X--    Until the end of 1987,
  453. X--    Consulting to Sun's East Coast Division:
  454. X--        gmcgary@ecd.sun.com
  455. X--        gmcgary@suneast.uu.net
  456. X--
  457. X--    After that, probably consulting in Europe...
  458. END_OF_FILE
  459. if test 16037 -ne `wc -c <'TUTORIAL'`; then
  460.     echo shar: \"'TUTORIAL'\" unpacked with wrong size!
  461. fi
  462. # end of 'TUTORIAL'
  463. fi
  464. if test -f 'iid.y' -a "${1}" != "-c" ; then 
  465.   echo shar: Will not clobber existing file \"'iid.y'\"
  466. else
  467. echo shar: Extracting \"'iid.y'\" \(11278 characters\)
  468. sed "s/^X//" >'iid.y' <<'END_OF_FILE'
  469. X%{
  470. X/* This is the yacc definition for the iid command language.
  471. X * The main program, scanner, and parser are defined here.
  472. X * The utility functions invoked from here are in iidfun.c
  473. X */
  474. X
  475. X#include "iiddef.h"
  476. X
  477. X%}
  478. X
  479. X%union {
  480. X   set_type *     setdef ;   
  481. X   id_type *      strdef ;
  482. X   id_list_type * listdef ;
  483. X}
  484. X
  485. X%token < setdef > SET
  486. X
  487. X%token < strdef > ID SHELL_QUERY SHELL_COMMAND
  488. X
  489. X%type < setdef > Query Primitive
  490. X
  491. X%type < listdef > Lid_group Aid_group Id_list Command_list
  492. X
  493. X%token LID AID BEGIN SETS SS FILES SHOW HELP OFF MATCH
  494. X
  495. X%left OR
  496. X
  497. X%left AND
  498. X
  499. X%left NOT
  500. X
  501. X%start Command
  502. X
  503. X%%
  504. X
  505. XCommand :
  506. X   BEGIN ID
  507. X      {
  508. X         /* cd to the directory specified as argument, flush sets */
  509. X
  510. X         SetDirectory($2) ;
  511. X         FlushSets() ;
  512. X      }
  513. X|  Set_query Query
  514. X|  File_query Query
  515. X      {
  516. X         /* print the list of files resulting from Query */
  517. X
  518. X         PrintSet($2) ;
  519. X      }
  520. X|  SHOW SET
  521. X      {
  522. X         /* run PAGER on the list of files in SET */
  523. X
  524. X         RunPager(Pager, $2) ;
  525. X      }
  526. X|  SETS
  527. X      {
  528. X         /* describe sets created so far */
  529. X
  530. X         DescribeSets() ;
  531. X      }
  532. X|  HELP
  533. X      {
  534. X         /* run PAGER on the help file */
  535. X
  536. X         RunPager(Pager, HelpSet) ;
  537. X      }
  538. X|  OFF
  539. X      {
  540. X         exit(0) ;
  541. X      }
  542. X| SHELL_QUERY Command_list
  543. X      {
  544. X         /* run the shell command and eat the results as a file set */
  545. X
  546. X         OneDescription(RunProg($1->id, $2)) ;
  547. X         free($1) ;
  548. X      }
  549. X| SHELL_COMMAND Command_list
  550. X      {
  551. X         /* run the shell command */
  552. X
  553. X         RunShell($1->id, $2) ;
  554. X         free($1) ;
  555. X      }
  556. X;
  557. X
  558. XSet_query :
  559. X   SS
  560. X      {
  561. X         /* Turn on verbose query flag */
  562. X
  563. X         VerboseQuery = TRUE ;
  564. X      }
  565. X;
  566. X
  567. XFile_query :
  568. X   FILES
  569. X      {
  570. X         /* Turn off verbose query flag */
  571. X
  572. X         VerboseQuery = FALSE ;
  573. X      }
  574. X;
  575. X
  576. XQuery :
  577. X   Primitive
  578. X      {
  579. X         /* value of query is set associated with primitive */
  580. X
  581. X         $$ = $1 ;
  582. X      }
  583. X|  Query AND Query
  584. X      {
  585. X         /* value of query is intersection of the two query sets */
  586. X
  587. X         $$ = SetIntersect($1, $3) ;
  588. X         if (VerboseQuery) {
  589. X            OneDescription($$) ;
  590. X         }
  591. X      }
  592. X|  Query OR Query
  593. X      {
  594. X         /* value of query is union of the two query sets */
  595. X
  596. X         $$ = SetUnion($1, $3) ;
  597. X         if (VerboseQuery) {
  598. X            OneDescription($$) ;
  599. X         }
  600. X      }
  601. X|  NOT Query
  602. X      {
  603. X         /* value of query is inverse of other query */
  604. X         
  605. X         $$ = SetInverse($2) ;
  606. X         if (VerboseQuery) {
  607. X            OneDescription($$) ;
  608. X         }
  609. X      }
  610. X;
  611. X
  612. XPrimitive :
  613. X   SET
  614. X      {
  615. X         /* Value of primitive is value of recorded set */
  616. X
  617. X         $$ = $1 ;
  618. X      }
  619. X|  Lid_group
  620. X      {
  621. X         /* Value of primitive is obtained by running an lid query */
  622. X
  623. X         $$ = RunProg(LidCommand, $1) ;
  624. X         if (VerboseQuery) {
  625. X            OneDescription($$) ;
  626. X         }
  627. X      }
  628. X|  Aid_group
  629. X      {
  630. X         /* Value of primitive is obtained by running an aid query */
  631. X
  632. X         $$ = RunProg("aid -kmn", $1) ;
  633. X         if (VerboseQuery) {
  634. X            OneDescription($$) ;
  635. X         }
  636. X      }
  637. X|  MATCH Id_list
  638. X      {
  639. X         /* Match names from database against pattern */
  640. X         $$ = RunProg("pid -kmn", $2) ;
  641. X         if (VerboseQuery) {
  642. X            OneDescription($$) ;
  643. X         }
  644. X      }
  645. X|  '(' Query ')'
  646. X      {
  647. X         /* value of primitive is value of query */
  648. X
  649. X         $$ = $2 ;
  650. X      }
  651. X;
  652. X
  653. XLid_group :
  654. X   ID
  655. X      {
  656. X         /* make arg list holding single ID */
  657. X
  658. X         $$ = InitList() ;
  659. X         $$ = ExtendList($$, $1) ;
  660. X         LidCommand = DefaultCommand ;
  661. X      }
  662. X|  LID Id_list
  663. X      {
  664. X         /* arg list is Id_list */
  665. X
  666. X         $$ = $2 ;
  667. X         LidCommand = "lid -kmn" ;
  668. X      }
  669. X;
  670. X
  671. XAid_group :
  672. X   AID Id_list
  673. X      {
  674. X         /* arg list is Id_list */
  675. X
  676. X         $$ = $2 ;
  677. X      }
  678. X;
  679. X
  680. XCommand_list :
  681. X   ID
  682. X      {
  683. X         /* make arg list holding single ID */
  684. X
  685. X         $$ = InitList() ;
  686. X         $$ = ExtendList($$, $1) ;
  687. X      }
  688. X|  SET
  689. X      {
  690. X         /* make arg list holding names from set */
  691. X
  692. X         $$ = InitList() ;
  693. X         $$ = SetList($$, $1) ;
  694. X      }
  695. X|  Command_list ID
  696. X      {
  697. X         /* extend arg list with additional ID */
  698. X
  699. X         $$ = ExtendList($1, $2) ;
  700. X      }
  701. X|  Command_list SET
  702. X      {
  703. X         /* extend arg list with additional file names */
  704. X
  705. X         $$ = SetList($1, $2) ;
  706. X      }
  707. X;
  708. X
  709. XId_list :
  710. X   ID
  711. X      {
  712. X         /* make arg list holding single ID */
  713. X
  714. X         $$ = InitList() ;
  715. X         $$ = ExtendList($$, $1) ;
  716. X      }
  717. X|  Id_list ID
  718. X      {
  719. X         /* extend arg list with additional ID */
  720. X
  721. X         $$ = ExtendList($1, $2) ;
  722. X      }
  723. X;
  724. X
  725. X%%
  726. X
  727. X/* ScanLine - a global variable holding a pointer to the current
  728. X * command being scanned.
  729. X */
  730. Xchar *             ScanLine ;
  731. X
  732. X/* ScanPtr - a global pointer to the current scan position in ScanLine.
  733. X */
  734. Xchar *             ScanPtr ;
  735. X
  736. X/* yytext - buffer holding the token.
  737. X */
  738. Xchar               yytext [ MAXCMD ] ;
  739. X
  740. X/* yyerror - process syntax errors.
  741. X */
  742. Xint
  743. Xyyerror(s)
  744. X   char *     s ;
  745. X{
  746. X   if (*ScanPtr == '\0') {
  747. X      fprintf(stderr,"Syntax error near end of command.\n") ;
  748. X   } else {
  749. X      fprintf(stderr,"Syntax error on or before %s\n",ScanPtr) ;
  750. X   }
  751. X   return(0) ;
  752. X}
  753. X
  754. X/* ScanInit - initialize the yylex routine for the new line of input.
  755. X * Basically just initializes the global variables that hold the char
  756. X * ptrs the scanner uses.
  757. X */
  758. Xvoid
  759. XScanInit(line)
  760. X   char *    line ;
  761. X{
  762. X   /* skip the leading white space - the yylex routine is sensitive
  763. X    * to keywords in the first position on the command line.
  764. X    */
  765. X   
  766. X   while (isspace(*line)) ++line ;
  767. X   ScanLine = line ;
  768. X   ScanPtr = line ;
  769. X}
  770. X
  771. X/* NameEq - compare two names for equality in a case insensitive manner.
  772. X * return TRUE for equal, FALSE otherwise.
  773. X */
  774. Xint
  775. XNameEq(n1,n2)
  776. X   char *      n1 ;
  777. X   char *      n2 ;
  778. X{
  779. X   char        c1 ;
  780. X   char        c2 ;
  781. X   
  782. X   for ( ; ; ) {
  783. X      c1 = *n1++ ;
  784. X      c2 = *n2++ ;
  785. X      if (isalpha(c1)) c1 = tolower(c1) ;
  786. X      if (isalpha(c2)) c2 = tolower(c2) ;
  787. X      if (c1 != c2) return FALSE ;
  788. X      if (c1 == '\0') return TRUE ;
  789. X   }
  790. X}
  791. X
  792. X/* yylex - the scanner for iid. Basically a kludge ad-hoc piece of junk,
  793. X * but what the heck, if it works...
  794. X *
  795. X * Mostly just scans for non white space strings and returns ID for them.
  796. X * Does check especially for '(' and ')'. Just before returning ID it
  797. X * checks for command names if it is the first token on line or
  798. X * AND, OR, LID, AID if it is in the middle of a line.
  799. X */
  800. Xint
  801. Xyylex()
  802. X{
  803. X   char *      bp ;
  804. X   char        c ;
  805. X   int         code = ID ;
  806. X   char *      dp ;
  807. X   char *      sp ;
  808. X   int         val ;
  809. X   
  810. X   bp = ScanPtr ;
  811. X   while (isspace(*bp)) ++bp ;
  812. X   sp = bp ;
  813. X   c = *sp++ ;
  814. X   if ((c == '(') || (c == ')') || (c == '\0')) {
  815. X      ScanPtr = sp ;
  816. X      if (c == '\0') {
  817. X         --ScanPtr ;
  818. X      }
  819. X      return(c) ;
  820. X   } else {
  821. X      dp = yytext ;
  822. X      while (! ((c == '(') || (c == ')') || (c == '\0') || isspace(c))) {
  823. X         *dp++ = c ;
  824. X         c = *sp++ ;
  825. X      }
  826. X      *dp++ = '\0' ;
  827. X      ScanPtr = sp - 1 ;
  828. X      if (bp == ScanLine) {
  829. X
  830. X         /* first token on line, check for command names */
  831. X
  832. X         if (NameEq(yytext, "SS")) return(SS) ;
  833. X         if (NameEq(yytext, "FILES")) return(FILES) ;
  834. X         if (NameEq(yytext, "F")) return(FILES) ;
  835. X         if (NameEq(yytext, "HELP")) return(HELP) ;
  836. X         if (NameEq(yytext, "H")) return(HELP) ;
  837. X         if (NameEq(yytext, "?")) return(HELP) ;
  838. X         if (NameEq(yytext, "BEGIN")) return(BEGIN) ;
  839. X         if (NameEq(yytext, "B")) return(BEGIN) ;
  840. X         if (NameEq(yytext, "SETS")) return(SETS) ;
  841. X         if (NameEq(yytext, "SHOW")) return(SHOW) ;
  842. X         if (NameEq(yytext, "P")) return(SHOW) ;
  843. X         if (NameEq(yytext, "OFF")) return(OFF) ;
  844. X         if (NameEq(yytext, "Q")) return(OFF) ;
  845. X         if (NameEq(yytext, "QUIT")) return(OFF) ;
  846. X         if (yytext[0] == '!') {
  847. X            code = SHELL_COMMAND ;
  848. X         } else {
  849. X            code = SHELL_QUERY ;
  850. X         }
  851. X      } else {
  852. X
  853. X         /* not first token, check for operator names */
  854. X
  855. X         if (NameEq(yytext, "LID")) return(LID) ;
  856. X         if (NameEq(yytext, "AID")) return(AID) ;
  857. X         if (NameEq(yytext, "AND")) return(AND) ;
  858. X         if (NameEq(yytext, "OR")) return(OR) ;
  859. X         if (NameEq(yytext, "NOT")) return(NOT) ;
  860. X         if (NameEq(yytext, "MATCH")) return(MATCH) ;
  861. X         if ((yytext[0] == 's' || yytext[0] == 'S') && isdigit(yytext[1])) {
  862. X            
  863. X            /* this might be a set specification */
  864. X            
  865. X            sp = &yytext[1] ;
  866. X            val = 0 ;
  867. X            for ( ; ; ) {
  868. X               c = *sp++ ;
  869. X               if (c == '\0') {
  870. X                  if (val < NextSetNum) {
  871. X                     yylval.setdef = TheSets[val] ;
  872. X                     return(SET) ;
  873. X                  }
  874. X               }
  875. X               if (isdigit(c)) {
  876. X                  val = (val * 10) + (c - '0') ;
  877. X               } else {
  878. X                  break ;
  879. X               }
  880. X            }
  881. X         }
  882. X      }
  883. X      yylval.strdef = (id_type *)malloc(sizeof(id_type) + strlen(yytext)) ;
  884. X      if (yylval.strdef == NULL) {
  885. X         fatal("Out of memory in yylex") ;
  886. X      }
  887. X      yylval.strdef->next_id = NULL ;
  888. X      if (code == SHELL_COMMAND) {
  889. X         strcpy(yylval.strdef->id, &yytext[1]) ;
  890. X      } else {
  891. X         strcpy(yylval.strdef->id, yytext) ;
  892. X      }
  893. X      return(code) ;
  894. X   }
  895. X}
  896. X
  897. X/* The main program for iid - parse the command line, initialize processing,
  898. X * loop processing one command at a time.
  899. X */
  900. Xmain(argc, argv)
  901. X   int         argc ;
  902. X   char *      argv [ ] ;
  903. X{
  904. X   int         c ;                     /* current option */
  905. X   char *      CmdPtr ;                /* Points to the command string */
  906. X   char        Command [ MAXCMD ] ;    /* Buffer for reading commands */
  907. X   int         Do1 = FALSE ;           /* TRUE if should only do 1 command */
  908. X   int         DoPrompt ;              /* TRUE if should write a prompt */
  909. X   int         errors = 0 ;            /* error count */
  910. X
  911. X   DoPrompt = isatty(fileno(stdin)) ;
  912. X   while ((c = getopt(argc, argv, "Hac:")) != EOF) {
  913. X      switch(c) {
  914. X      case 'a':
  915. X         DefaultCommand = "aid -kmn" ;
  916. X         break ;
  917. X      case 'c':
  918. X         CmdPtr = optarg ;
  919. X         Do1 = TRUE ;
  920. X         break ;
  921. X      case 'H':
  922. X         fputs("\
  923. Xiid: interactive ID database query tool. Call with:\n\
  924. X   iid [-a] [-c] [-H]\n\
  925. X\n\
  926. X-a\tUse the aid as the default query command (not lid).\n\
  927. X-c cmd\tExecute the single query cmd and exit.\n\
  928. X-H\tPrint this message and exit.\n\
  929. X\n\
  930. XTo get help after starting program type 'help'.\n\
  931. X",stderr) ;
  932. X         exit(0) ;
  933. X      default:
  934. X         ++errors ;
  935. X         break ;
  936. X      }
  937. X   }
  938. X   if (argc != optind) {
  939. X      fputs("iid: Excess arguments ignored.\n",stderr) ;
  940. X      ++errors ;
  941. X   }
  942. X   if (errors) {
  943. X      fputs("run iid -H for help.\n",stderr) ;
  944. X      exit(1) ;
  945. X   }
  946. X
  947. X   /* initialize global data */
  948. X
  949. X   InitIid() ;
  950. X
  951. X   /* run the parser */
  952. X
  953. X   if (Do1) {           
  954. X      ScanInit(CmdPtr) ;
  955. X      exit(yyparse()) ;
  956. X   } else {
  957. X      for ( ; ; ) {
  958. X         if (DoPrompt) {
  959. X            fputs(Prompt, stdout) ;
  960. X            fflush(stdout) ;
  961. X         }
  962. X         gets(Command) ;
  963. X         if (feof(stdin)) {
  964. X            if (DoPrompt) fputs("\n", stdout) ;
  965. X            strcpy(Command, "off") ;
  966. X         }
  967. X         ScanInit(Command) ;
  968. X         errors += yyparse() ;
  969. X      }
  970. X   }
  971. X}
  972. END_OF_FILE
  973. if test 11278 -ne `wc -c <'iid.y'`; then
  974.     echo shar: \"'iid.y'\" unpacked with wrong size!
  975. fi
  976. # end of 'iid.y'
  977. fi
  978. if test -f 'scan-c.c' -a "${1}" != "-c" ; then 
  979.   echo shar: Will not clobber existing file \"'scan-c.c'\"
  980. else
  981. echo shar: Extracting \"'scan-c.c'\" \(8401 characters\)
  982. sed "s/^X//" >'scan-c.c' <<'END_OF_FILE'
  983. X/* Copyright (c) 1986, Greg McGary */
  984. X/* Vhil scanning mods added Jan 7th, 1988 by Tom Horsley */
  985. Xstatic char sccsid[] = "@(#)scan-c.c    1.1 86/10/09";
  986. X
  987. X#include    <bool.h>
  988. X#include    <stdio.h>
  989. X#include    <string.h>
  990. X#include    <id.h>
  991. X
  992. Xchar *getCId();
  993. Xchar *getVhilId();
  994. Xvoid setCArgs();
  995. X
  996. Xstatic void clrCtype();
  997. Xstatic void setCtype();
  998. X
  999. X#define    I1    0x0001    /* 1st char of an identifier [a-zA-Z_] */
  1000. X#define    DG    0x0002    /* decimal digit [0-9] */
  1001. X#define    NM    0x0004    /* extra chars in a hex or long number [a-fA-FxXlL] */
  1002. X#define    C1    0x0008    /* C comment introduction char: / */
  1003. X#define    C2    0x0010    /* C comment termination  char: * */
  1004. X#define    Q1    0x0020    /* single quote: ' */
  1005. X#define    Q2    0x0040    /* double quote: " */
  1006. X#define    ES    0x0080    /* escape char: \ */
  1007. X#define    NL    0x0100    /* newline: \n */
  1008. X#define    EF    0x0200    /* EOF */
  1009. X#define    SK    0x0400    /* Make these chars valid for names within strings */
  1010. X#define    VH    0x0800    /* VHIL comment introduction char: # */
  1011. X#define    WS    0x1000    /* White space characters */
  1012. X
  1013. X/*
  1014. X    character class membership macros:
  1015. X*/
  1016. X#define    ISDIGIT(c)    ((rct)[c]&(DG))        /* digit */
  1017. X#define    ISNUMBER(c)    ((rct)[c]&(DG|NM))    /* legal in a number */
  1018. X#define    ISEOF(c)    ((rct)[c]&(EF))        /* EOF */
  1019. X#define    ISID1ST(c)    ((rct)[c]&(I1))        /* 1st char of an identifier */
  1020. X#define    ISIDREST(c)    ((rct)[c]&(I1|DG))    /* rest of an identifier */
  1021. X#define    ISSTRKEEP(c)    ((rct)[c]&(I1|DG|SK))    /* keep contents of string */
  1022. X#define    ISSPACE(c)    ((rct)[c]&(WS))        /* white space character */
  1023. X/*
  1024. X    The `BORING' classes should be skipped over
  1025. X    until something interesting comes along...
  1026. X*/
  1027. X#define    ISBORING(c)    (!((rct)[c]&(EF|NL|I1|DG|Q1|Q2|C1|VH)))    /* fluff */
  1028. X#define    ISCBORING(c)    (!((rct)[c]&(EF|C2)))    /* comment fluff */
  1029. X#define    ISVBORING(c)    (!((rct)[c]&(EF|NL)))    /* vhil comment fluff */
  1030. X#define    ISQ1BORING(c)    (!((rct)[c]&(EF|NL|Q1|ES)))    /* char const fluff */
  1031. X#define    ISQ2BORING(c)    (!((rct)[c]&(EF|NL|Q2|ES)))    /* quoted str fluff */
  1032. X
  1033. Xstatic short idctype[] = {
  1034. X
  1035. X    EF,
  1036. X
  1037. X    /*      0       1       2       3       4       5       6       7   */
  1038. X    /*    -----   -----   -----   -----   -----   -----   -----   ----- */
  1039. X
  1040. X    /*000*/    0,    0,    0,    0,    0,    0,    0,    0,
  1041. X    /*010*/    0,    0,    NL,    0,    0,    0,    0,    0,
  1042. X    /*020*/    0,    0,    0,    0,    0,    0,    0,    0,
  1043. X    /*030*/    0,    0,    0,    0,    0,    0,    0,    0,
  1044. X    /*040*/    0,    0,    Q2,    0,    0,    0,    0,    Q1,
  1045. X    /*050*/    0,    0,    C2,    0,    0,    0,    0,    C1,
  1046. X    /*060*/    DG,    DG,    DG,    DG,    DG,    DG,    DG,    DG,    
  1047. X    /*070*/    DG,    DG,    0,    0,    0,    0,    0,    0,
  1048. X    /*100*/    0,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1,
  1049. X    /*110*/    I1,    I1,    I1,    I1,    I1|NM,    I1,    I1,    I1,
  1050. X    /*120*/    I1,    I1,    I1,    I1,    I1,    I1,    I1,    I1,
  1051. X    /*130*/    I1|NM,    I1,    I1,    0,    ES,    0,    0,    I1,
  1052. X    /*140*/    0,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1,
  1053. X    /*150*/    I1,    I1,    I1,    I1,    I1|NM,    I1,    I1,    I1,
  1054. X    /*160*/    I1,    I1,    I1,    I1,    I1,    I1,    I1,    I1,
  1055. X    /*170*/    I1|NM,    I1,    I1,    0,    0,    0,    0,    0,
  1056. X
  1057. X    /*200*/    0,    0,    0,    0,    0,    0,    0,    0,
  1058. X    /*210*/    0,    0,    0,    0,    0,    0,    0,    0,
  1059. X    /*220*/    0,    0,    0,    0,    0,    0,    0,    0,
  1060. X    /*230*/    0,    0,    0,    0,    0,    0,    0,    0,
  1061. X    /*240*/    0,    0,    0,    0,    0,    0,    0,    0,
  1062. X    /*250*/    0,    0,    0,    0,    0,    0,    0,    0,
  1063. X    /*260*/    0,    0,    0,    0,    0,    0,    0,    0,
  1064. X    /*270*/    0,    0,    0,    0,    0,    0,    0,    0,
  1065. X    /*300*/    0,    0,    0,    0,    0,    0,    0,    0,
  1066. X    /*310*/    0,    0,    0,    0,    0,    0,    0,    0,
  1067. X    /*320*/    0,    0,    0,    0,    0,    0,    0,    0,
  1068. X    /*330*/    0,    0,    0,    0,    0,    0,    0,    0,
  1069. X    /*340*/    0,    0,    0,    0,    0,    0,    0,    0,
  1070. X    /*350*/    0,    0,    0,    0,    0,    0,    0,    0,
  1071. X    /*360*/    0,    0,    0,    0,    0,    0,    0,    0,
  1072. X    /*370*/    0,    0,    0,    0,    0,    0,    0,    0,
  1073. X
  1074. X};
  1075. X
  1076. Xstatic bool eatUnder = TRUE;
  1077. Xstatic bool scanVhil = FALSE;
  1078. X
  1079. X/*
  1080. X*/
  1081. Xchar *
  1082. XgetVhilId(inFILE, flagP)
  1083. X{
  1084. X    if (! scanVhil) {
  1085. X        setCArgs("vhil",'+',"v");
  1086. X    }
  1087. X    return(getCId(inFILE, flagP));
  1088. X}
  1089. X
  1090. X/*
  1091. X    Grab the next identifier the C source
  1092. X    file opened with the handle `inFILE'.
  1093. X    This state machine is built for speed, not elegance.
  1094. X*/
  1095. Xchar *
  1096. XgetCId(inFILE, flagP)
  1097. X    FILE        *inFILE;
  1098. X    int        *flagP;
  1099. X{
  1100. X    static char    idBuf[BUFSIZ];
  1101. X    static bool    newLine = TRUE;
  1102. X    register short    *rct = &idctype[1];
  1103. X    register int    c;
  1104. X    register char    *id = idBuf;
  1105. X
  1106. Xtop:
  1107. X    c = getc(inFILE);
  1108. X    if (newLine) {
  1109. X        newLine = FALSE;
  1110. X        if (c == '.') {
  1111. X            /* Auto-recognize vhil code when you see a . in column 1.
  1112. X             * also ignore lines that start with a .
  1113. X             */
  1114. X            if (! scanVhil) {
  1115. X                setCArgs("vhil",'+',"v");
  1116. X            }
  1117. X            while (ISVBORING(c))
  1118. X                c = getc(inFILE);
  1119. X            newLine = TRUE;
  1120. X            goto top;
  1121. X        }
  1122. X        if (c != '#')
  1123. X            goto next;
  1124. X        c = getc(inFILE);
  1125. X        if (scanVhil && ISSPACE(c)) {
  1126. X            while (ISVBORING(c))
  1127. X                c = getc(inFILE);
  1128. X            newLine = TRUE;
  1129. X            goto top;
  1130. X        }
  1131. X        while (ISBORING(c))
  1132. X            c = getc(inFILE);
  1133. X        if (!ISID1ST(c))
  1134. X            goto next;
  1135. X        id = idBuf;
  1136. X        *id++ = c;
  1137. X        while (ISIDREST(c = getc(inFILE)))
  1138. X            *id++ = c;
  1139. X        *id = '\0';
  1140. X        if (strequ(idBuf, "include")) {
  1141. X            while (c == ' ' || c == '\t') c = getc(inFILE) ;
  1142. X            if (c == '\n') {newLine = TRUE; goto top;}
  1143. X            id = idBuf;
  1144. X            if (c == '"') {
  1145. X                c = getc(inFILE);
  1146. X                while (c != '\n' && c != EOF && c != '"') {
  1147. X                    *id++ = c;
  1148. X                    c = getc(inFILE);
  1149. X                }
  1150. X                *flagP = IDN_STRING;
  1151. X            } else if (c == '<') {
  1152. X                c = getc(inFILE);
  1153. X                while (c != '\n' && c != EOF && c != '>') {
  1154. X                    *id++ = c;
  1155. X                    c = getc(inFILE);
  1156. X                }
  1157. X                *flagP = IDN_STRING;
  1158. X            } else if (ISID1ST(c)) {
  1159. X                *id++ = c ;
  1160. X                while (ISIDREST(c = getc(inFILE))) *id++ = c;
  1161. X                *flagP = IDN_NAME;
  1162. X            } else {
  1163. X                while (c != '\n' && c != EOF) c = getc(inFILE);
  1164. X                newLine = TRUE;
  1165. X                goto top;
  1166. X            }
  1167. X            while (c != '\n' && c != EOF) c = getc(inFILE) ;
  1168. X            newLine = TRUE;
  1169. X            *id = '\0';
  1170. X            return idBuf;
  1171. X        }
  1172. X        if (strnequ(idBuf, "if", 2)
  1173. X        || strequ(idBuf, "define")
  1174. X        || strequ(idBuf, "elif")         /* ansi C */
  1175. X        || (scanVhil && strequ(idBuf, "elsif"))
  1176. X        || strequ(idBuf, "undef"))
  1177. X            goto next;
  1178. X        while ((c != '\n') && (c != EOF))
  1179. X            c = getc(inFILE);
  1180. X        newLine = TRUE;
  1181. X        goto top;
  1182. X    }
  1183. X
  1184. Xnext:
  1185. X    while (ISBORING(c))
  1186. X        c = getc(inFILE);
  1187. X
  1188. X    switch (c)
  1189. X    {
  1190. X    case '"':
  1191. X        id = idBuf;
  1192. X        *id++ = c = getc(inFILE);
  1193. X        for (;;) {
  1194. X            while (ISQ2BORING(c))
  1195. X                *id++ = c = getc(inFILE);
  1196. X            if (c == '\\') {
  1197. X                *id++ = c = getc(inFILE);
  1198. X                continue;
  1199. X            } else if (c != '"')
  1200. X                goto next;
  1201. X            break;
  1202. X        }
  1203. X        *--id = '\0';
  1204. X        id = idBuf;
  1205. X        while (ISSTRKEEP(*id))
  1206. X            id++;
  1207. X        if (*id || id == idBuf) {
  1208. X            c = getc(inFILE);
  1209. X            goto next;
  1210. X        }
  1211. X        *flagP = IDN_STRING;
  1212. X        if (eatUnder && idBuf[0] == '_' && idBuf[1])
  1213. X            return &idBuf[1];
  1214. X        else
  1215. X            return idBuf;
  1216. X        
  1217. X    case '\'':
  1218. X        c = getc(inFILE);
  1219. X        for (;;) {
  1220. X            while (ISQ1BORING(c))
  1221. X                c = getc(inFILE);
  1222. X            if (c == '\\') {
  1223. X                c = getc(inFILE);
  1224. X                continue;
  1225. X            } else if (c == '\'')
  1226. X                c = getc(inFILE);
  1227. X            goto next;
  1228. X        }
  1229. X
  1230. X    case '/':
  1231. X        if ((c = getc(inFILE)) != '*')
  1232. X            goto next;
  1233. X        c = getc(inFILE);
  1234. X        for (;;) {
  1235. X            while (ISCBORING(c))
  1236. X                c = getc(inFILE);
  1237. X            if ((c = getc(inFILE)) == '/') {
  1238. X                c = getc(inFILE);
  1239. X                goto next;
  1240. X            } else if (ISEOF(c)) {
  1241. X                newLine = TRUE;
  1242. X                return NULL;
  1243. X            }
  1244. X        }
  1245. X
  1246. X    case '\n':
  1247. X        newLine = TRUE;
  1248. X        goto top;
  1249. X
  1250. X    case '#':
  1251. X        if (! scanVhil) {
  1252. X            /* Auto-recognize vhil when find a # in the middle of a line.
  1253. X             */
  1254. X            setCArgs("vhil",'+',"v");
  1255. X        }
  1256. X        c = getc(inFILE);
  1257. X        while (ISVBORING(c))
  1258. X            c = getc(inFILE);
  1259. X        newLine = TRUE;
  1260. X        goto top;
  1261. X    default:
  1262. X        if (ISEOF(c)) {
  1263. X            newLine = TRUE;
  1264. X            return NULL;
  1265. X        }
  1266. X    name:
  1267. X        id = idBuf;
  1268. X        *id++ = c;
  1269. X        if (ISID1ST(c)) {
  1270. X            *flagP = IDN_NAME;
  1271. X            while (ISIDREST(c = getc(inFILE)))
  1272. X                *id++ = c;
  1273. X        } else if (ISDIGIT(c)) {
  1274. X            *flagP = IDN_NUMBER;
  1275. X            while (ISNUMBER(c = getc(inFILE)))
  1276. X                *id++ = c;
  1277. X        } else
  1278. X            fprintf(stderr, "junk: `\\%3o'", c);
  1279. X        ungetc(c, inFILE);
  1280. X        *id = '\0';
  1281. X        *flagP |= IDN_LITERAL;
  1282. X        return idBuf;
  1283. X    }
  1284. X}
  1285. X
  1286. Xstatic void
  1287. XsetCtype(chars, type)
  1288. X    char        *chars;
  1289. X    int        type;
  1290. X{
  1291. X    short        *rct = &idctype[1];
  1292. X
  1293. X    while (*chars)
  1294. X        rct[*chars++] |= type;
  1295. X}
  1296. Xstatic void
  1297. XclrCtype(chars, type)
  1298. X    char        *chars;
  1299. X    int        type;
  1300. X{
  1301. X    short        *rct = &idctype[1];
  1302. X
  1303. X    while (*chars)
  1304. X        rct[*chars++] &= ~type;
  1305. X}
  1306. X
  1307. Xextern char    *MyName;
  1308. Xstatic void
  1309. Xusage(lang)
  1310. X    char        *lang;
  1311. X{
  1312. X    fprintf(stderr, "Usage: %s does not accept %s scanner arguments\n", MyName, lang);
  1313. X    exit(1);
  1314. X}
  1315. Xstatic char *cDocument[] =
  1316. X{
  1317. X"The C scanner arguments take the form -Sc<arg>, where <arg>",
  1318. X"is one of the following: (<cc> denotes one or more characters)",
  1319. X"  (+|-)u . . . . (Do|Don't) strip a leading `_' from ids in strings.",
  1320. X"  -s<cc> . . . . Allow <cc> in string ids.",
  1321. X"  -v . . . . . . Skip vhil comments.",
  1322. XNULL
  1323. X};
  1324. Xvoid
  1325. XsetCArgs(lang, op, arg)
  1326. X    char        *lang;
  1327. X    int        op;
  1328. X    char        *arg;
  1329. X{
  1330. X    if (op == '?') {
  1331. X        document(cDocument);
  1332. X        return;
  1333. X    }
  1334. X    switch (*arg++)
  1335. X    {
  1336. X    case 'u':
  1337. X        eatUnder = (op == '+');
  1338. X        break;
  1339. X    case 's':
  1340. X        setCtype(arg, SK);
  1341. X        break;
  1342. X    case 'v':
  1343. X        setCtype("$", I1);
  1344. X        setCtype("#", VH);
  1345. X        setCtype(" \t", WS);
  1346. X        scanVhil = TRUE;
  1347. X        break;
  1348. X    default:
  1349. X        if (lang)
  1350. X            usage(lang);
  1351. X        break;
  1352. X    }
  1353. X}
  1354. END_OF_FILE
  1355. if test 8401 -ne `wc -c <'scan-c.c'`; then
  1356.     echo shar: \"'scan-c.c'\" unpacked with wrong size!
  1357. fi
  1358. # end of 'scan-c.c'
  1359. fi
  1360. echo shar: End of archive 4 \(of 7\).
  1361. cp /dev/null ark4isdone
  1362. MISSING=""
  1363. for I in 1 2 3 4 5 6 7 ; do
  1364.     if test ! -f ark${I}isdone ; then
  1365.     MISSING="${MISSING} ${I}"
  1366.     fi
  1367. done
  1368. if test "${MISSING}" = "" ; then
  1369.     echo You have unpacked all 7 archives.
  1370.     rm -f ark[1-9]isdone
  1371. else
  1372.     echo You still need to unpack the following archives:
  1373.     echo "        " ${MISSING}
  1374. fi
  1375. ##  End of shell archive.
  1376. exit 0
  1377.  
  1378. exit 0 # Just in case...
  1379.